package drds.common.db.sql_mapping.sql_execute;


import drds.common.Constants;
import drds.common.db.sql_mapping.configuration.Configuration;
import drds.common.db.sql_mapping.dynamic_tag.sql_template.Bind;
import drds.common.db.sql_mapping.dynamic_tag.token_handler.PreparedParameterMapping;
import drds.common.db.sql_mapping.sql_execute.primary_key_generator.AutoSetModePrimaryKeyGenerator;
import drds.common.db.sql_mapping.sql_execute.primary_key_generator.PrimaryKeyGenerator;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class StatementHandlerImpl implements StatementHandler {

    @Setter
    @Getter
    private Configuration configuration;
    @Setter
    @Getter
    protected Mapper mapper;
    @Setter
    @Getter
    protected Bind bind;

    public StatementHandlerImpl(Mapper mapper, Bind bind) {
        this.configuration = mapper.getConfiguration();
        this.mapper = mapper;
        this.bind = bind;
    }

    public Statement prepareStatement(Connection connection) throws SQLException {
        String sql = bind.getSql();
        if (Constants.developMode) {
            log.debug("\nsql:" + sql);
        }
        if (mapper.getPrimaryKeyGenerator() instanceof AutoSetModePrimaryKeyGenerator) {
            return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
        } else {
            return connection.prepareStatement(sql);
        }
    }

    public void closeStatement(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    @Override
    public void parameterize(Statement statement) throws SQLException {
        PreparedStatement preparedStatement = (PreparedStatement) statement;
        List<PreparedParameterMapping> preparedParameterMappingList = bind.getPreparedParameterMappingList();
        if (preparedParameterMappingList != null) {
            Map<String, Object> map = (Map<String, Object>) bind.getParameterObject();
            for (int i = 0; i < preparedParameterMappingList.size(); i++) {
                PreparedParameterMapping preparedParameterMapping = preparedParameterMappingList.get(i);
                String columnName = preparedParameterMapping.getColumnName();
                String columnPrefix = preparedParameterMapping.getColumnPrefix();
                Object object = null;
                if (columnPrefix != null) {
                    object = map.get(columnPrefix);
                    if (object == null) {
                        throw new IllegalArgumentException("别名对应的参数不存在");
                    } else {
                        if (object instanceof HashMap) {
                            object = ((HashMap) object).get(columnName);
                        } else {
                            throw new IllegalArgumentException("含有别名对应的参数必须是map");
                        }
                    }

                } else {
                    object = map.get(columnName);
                }
                //最主要的是如何找到参数的index
                preparedStatement.setObject(i + 1, object);
            }
        }
    }

    @Override
    public void parameterizeForBatchInsert(Statement statement, List<Map<String, Object>> parameterObject) throws SQLException {
        PreparedStatement preparedStatement = (PreparedStatement) statement;
        List<PreparedParameterMapping> preparedParameterMappingList = bind.getPreparedParameterMappingList();
        if (preparedParameterMappingList != null) {
            for (Map<String, Object> map : parameterObject) {
                for (int i = 0; i < preparedParameterMappingList.size(); i++) {
                    PreparedParameterMapping preparedParameterMapping = preparedParameterMappingList.get(i);
                    String columnName = preparedParameterMapping.getColumnName();
                    //批量插入不支持columnPrefix
                    String columnPrefix = preparedParameterMapping.getColumnPrefix();
                    Object object = map.get(columnName);
                    preparedStatement.setObject(i + 1, object);
                }
            }
            preparedStatement.addBatch();
        }
    }

    @Override
    public int update(Statement statement) throws SQLException {
        PreparedStatement preparedStatement = (PreparedStatement) statement;
        preparedStatement.execute();
        int rowsCount = preparedStatement.getUpdateCount();
        Object parameterObject = bind.getParameterObject();
        PrimaryKeyGenerator primaryKeyGenerator = mapper.getPrimaryKeyGenerator();
        primaryKeyGenerator.insert(mapper, preparedStatement, parameterObject);
        preparedStatement.close();
        return rowsCount;
    }

    @Override
    public List<Map<String, Object>> query(Statement statement) throws SQLException {
        PreparedStatement preparedStatement = (PreparedStatement) statement;
        ResultSet resultSet = preparedStatement.executeQuery();
        List<Map<String, Object>> mapList = MapListBuilder.build(resultSet);
        resultSet.close();
        preparedStatement.close();
        return mapList;
    }


}
